//"This sample program is provided AS IS and may be used, executed, copied and modified without royalty payment by customer (a) for its own
//instruction and study, (b) in order to develop applications designed to run with an IBM WebSphere product, either for customer's own internal use
//or for redistribution by customer, as part of such an application, in customer's own products. "
//
//(C) COPYRIGHT International Business Machines Corp., 2005,2006
//All Rights Reserved * Licensed Materials - Property of IBM

package com;

import com.ibm.websphere.asynchbeans.EventSource;
import com.ibm.websphere.asynchbeans.WorkManager;

/**
 * This is a ThreadFactory base class which can be used to any of the Executors in the library. It
 * returns 'supported' daemon threads which are then used with the Executors when
 * they need a thread.  A WASThreadFactoryBase instance should not be shared amongst applications.
 * @author Billy Newport and Chris D Johnson
 */
public abstract class WASThreadFactoryBase
{
    
    /*
     * The WorkManager is proxied to allow applying the J2EE context of the 
     * thread when this WASThreadFactoryBase instance was created.
     * If we didn't use a WorkManager proxy, then the J2EE context would always be
     * that of the system which is probably none at all.
     */
	private WorkManager wmProxy;
	
	/**
	 * Create a proxy for the WorkManager instance so that in the future when
	 * we call a method on the proxy, it's called with the context of the caller
	 * of the constructor of this class. This is essential to give all daemon
	 * threads the same context. If we didn't do this then the Runnables would be
	 * executed using the context of the caller of newThread which would give
	 * an unpredictable context to each thread.
	 * @param wm the WorkManager to use for establishing our J2EE context.
	 */
	public WASThreadFactoryBase(WorkManager wm) 
	{
		super();
		
		// Create the WorkManager proxy which will take a snapshot of the
		// J2EE context at this moment in time.
		EventSource es = wm.createEventSource();
		
		// Our WorkManager is the only listener and will be the receiver for all calls
		// to our proxy.  Each call will be wrapped in the J2EE context that is
		// on the thread right now.
		es.addListener(wm);
		
		// Create the WorkManager proxy
		wmProxy = (WorkManager)es.getEventTrigger(WorkManager.class);
	}

	/**
	 * Start a new thread using a WorkManager daemon thread.  
	 * To accomplish this, we need to make a wrapper for the Runnable
	 * which implements Work and our IThread delegate interface. We then
	 * make a ThreadWrapper which delegates to the actual
	 * Thread being using by the daemon thread created.
	 * @param command the Runnable to run on the new thread.
	 */
	public Thread newThread(Runnable command) 
	{
	    // The Runnable is wrapped to allow us to attach the actual running
	    // thread to it once it starts.
		RunnableWrapper wrappedCommand = new RunnableWrapper(command);
		
		// The ThreadWrapper will ultimately start the command on a WorkManager
		// daemon thread.
		return new ThreadWrapper(wmProxy, wrappedCommand);
	}
}
